package com.crazyauntzhang.easyshopbackend.controller;

import com.crazyauntzhang.easyshopbackend.domain.Item;
import com.crazyauntzhang.easyshopbackend.domain.Stock;
import com.crazyauntzhang.easyshopbackend.domain.TurnoverFlow;
import com.crazyauntzhang.easyshopbackend.request.CashieringRequest;
import com.crazyauntzhang.easyshopbackend.request.FindStockRequest;
import com.crazyauntzhang.easyshopbackend.request.RefundRequest;
import com.crazyauntzhang.easyshopbackend.result.ResponseResult;
import com.crazyauntzhang.easyshopbackend.service.ItemService;
import com.crazyauntzhang.easyshopbackend.service.StockService;
import com.crazyauntzhang.easyshopbackend.service.TurnoverFlowService;
import com.crazyauntzhang.easyshopbackend.util.Token;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@RestController
public class CashieringController {

	private final StockService stockService;
	private final ItemService itemService;
	private final TurnoverFlowService turnoverFlowService;

	@Autowired
	public CashieringController(StockService stockService,
								ItemService itemService,
								TurnoverFlowService turnoverFlowService) {
		this.stockService = stockService;
		this.itemService = itemService;
		this.turnoverFlowService = turnoverFlowService;
	}

	/**
	 * 添加临时商品（扫描条形码）
	 *
	 * @param findStockRequest 商品条码请求体类
	 * @return 【库存（商品信息，库存数量）】【无此商品/库存】
	 */
	@PostMapping("/addTempItem")
	public ResponseResult<Object> addTempItem(@RequestBody FindStockRequest findStockRequest) throws IllegalAccessException {
		//从请求体对象获取要查询的商品条码
		String itemBarcode = findStockRequest.getItemBarcode();
		//判断商品存在性
		Item item = itemService.findItemByBarcode(itemBarcode);
		if (item == null)
			return new ResponseResult<>(10404, "Item Not Found");
		//判断库存存在性
		Stock stock = stockService.findStock(itemBarcode);
		if (stock == null)
			return new ResponseResult<>(10404, "Stock Not Found");
		//构造响应体内容
		Map<String, Object> addtempItemMap = new HashMap<>();
		//通过反射机制获取对象所有内容
		Class<? extends Item> itemClass = item.getClass();
		Field[] itemClassDeclaredFields = itemClass.getDeclaredFields();
		for (Field field : itemClassDeclaredFields) {
			field.setAccessible(true);
			addtempItemMap.put(field.getName(), field.get(item));
		}
		//写入库存量并返回响应体
		addtempItemMap.put("quantity", stock.getQuantity());
		return new ResponseResult<>(10200, "OK", addtempItemMap);
	}

	/**
	 * 收银
	 *
	 * @param token              请求头token
	 * @param cashieringRequests 收银请求体
	 * @return 【应收款金额】【无此商品/库存】【数量溢出】
	 */
	@PostMapping("/cashiering")
	public ResponseResult<Object> cashiering(@RequestHeader("Authorization") String token,
											 @RequestBody CashieringRequest[] cashieringRequests) {
		//从请求头token获取收银员ID
		Claims claims = Token.parseToken(token);
		String userID = (String) claims.get("userID");
		//遍历请求体，获取所有条码，依次判断商品及其库存是否存在，以及库存量是否足够
		//如果出现异常则停止遍历，立即返回异常响应
		for (CashieringRequest cashieringRequest : cashieringRequests) {
			Map<String, Object> cashieringResponseMap = new HashMap<>();
			String itemBarcode = cashieringRequest.getItemBarcode();
			Item item = itemService.findItemByBarcode(itemBarcode);
			if (item == null) {
				cashieringResponseMap.put("itemBarcode", itemBarcode);
				return new ResponseResult<>(10404, "Item Not Found", cashieringResponseMap);
			}
			Stock itemStock = stockService.findStock(itemBarcode);
			if (itemStock == null) {
				cashieringResponseMap.put("itemBarcode", itemBarcode);
				return new ResponseResult<>(10404, "Stock Not Found", cashieringResponseMap);
			}
			Double cashieringRequestQuantity = cashieringRequest.getQuantity();
			Double itemStockQuantity = itemStock.getQuantity();
			if (cashieringRequestQuantity > itemStockQuantity) {
				cashieringResponseMap.put("itemBarcode", itemBarcode);
				return new ResponseResult<>(10412, "Quantity Overflows", cashieringResponseMap);
			}
		}
		//生成流水产生时间，获取流水号
		LocalDateTime sequenceDateTime = LocalDateTime.now();
		String year = String.format("%04d", sequenceDateTime.getYear());
		String month = String.format("%02d", sequenceDateTime.getMonthValue());
		String day = String.format("%02d", sequenceDateTime.getDayOfMonth());
		String hour = String.format("%02d", sequenceDateTime.getHour());
		String minute = String.format("%02d", sequenceDateTime.getMinute());
		String second = String.format("%02d", sequenceDateTime.getSecond());
		String nano = String.format("%09d", sequenceDateTime.getNano());
		String sequenceNo = year + month + day + hour + minute + second + nano;
		//遍历请求体，计算消费总额
		double sumPrice = 0.0;
		for (CashieringRequest cashieringRequest : cashieringRequests) {
			//获取条码，查询条码得到商品对象
			String itemBarcode = cashieringRequest.getItemBarcode();
			Item item = itemService.findItemByBarcode(itemBarcode);
			Double requestQuantity = cashieringRequest.getQuantity();
			//计算消费总额
			Double price = item.getPrice();
			sumPrice += price * requestQuantity;
			//获取单品收益
			Double profit = price - item.getPurchasePrice();
			//添加收银流水
			turnoverFlowService.addFlow(sequenceNo, sequenceDateTime, userID, itemBarcode, 1, price,
					requestQuantity, profit, null, null);
		}
		//格式化应付款
		Double totalPrice = Double.valueOf(new BigDecimal(sumPrice).setScale(2, RoundingMode.HALF_UP)
				.toString());
		//构造响应体
		Map<String, Object> cashieringMap = new HashMap<>();
		cashieringMap.put("totalPrice", totalPrice);
		cashieringMap.put("sequenceNo", sequenceNo);
		cashieringMap.put("sequenceDateTime", sequenceDateTime);
		return new ResponseResult<>(10200, "OK", cashieringMap);
	}

	/**
	 * 退款
	 *
	 * @param token          请求头token
	 * @param refundRequests 退款请求体
	 * @return 退款响应体
	 */
	@PostMapping("/refund")
	public ResponseResult<Object> rufund(@RequestHeader("Authorization") String token,
										 @RequestBody RefundRequest[] refundRequests) {
		//遍历检查请求体内容合法性
		for (RefundRequest refundRequest : refundRequests) {
			Map<String, Object> refundResponseMap = new HashMap<>();
			String sequenceNo = refundRequest.getSequenceNo();
			String itemBarcode = refundRequest.getItemBarcode();
			TurnoverFlow turnoverFlow = turnoverFlowService.findFlowWithItemBarcode(sequenceNo, itemBarcode);
			if (turnoverFlow == null) {
				refundResponseMap.put("sequenceNo", sequenceNo);
				return new ResponseResult<>(10404, "TurnoverFlow Not Found", refundResponseMap);
			}
			Item item = itemService.findItemByBarcode(itemBarcode);
			if (item == null) {
				refundResponseMap.put("itemBarcode", itemBarcode);
				return new ResponseResult<>(10404, "Item Not Found", refundResponseMap);
			}
			Stock itemStock = stockService.findStock(itemBarcode);
			if (itemStock == null) {
				refundResponseMap.put("itemBarcode", itemBarcode);
				return new ResponseResult<>(10404, "Stock Not Found", refundResponseMap);
			}
			Double refundRequestQuantity = refundRequest.getQuantity();
			Double restQuantity = turnoverFlowService.findRestQuantity(sequenceNo, itemBarcode);
			if (refundRequestQuantity > restQuantity) {
				refundResponseMap.put("itemBarcode", itemBarcode);
				return new ResponseResult<>(10412, "Quantity Overflows", refundResponseMap);
			}
		}
		//获取处理退款的收银员ID
		Claims claims = Token.parseToken(token);
		String handlerID = (String) claims.get("userID");
		//生成流水产生时间，获取流水号
		LocalDateTime sequenceDateTime = LocalDateTime.now();
		String year = String.format("%04d", sequenceDateTime.getYear());
		String month = String.format("%02d", sequenceDateTime.getMonthValue());
		String day = String.format("%02d", sequenceDateTime.getDayOfMonth());
		String hour = String.format("%02d", sequenceDateTime.getHour());
		String minute = String.format("%02d", sequenceDateTime.getMinute());
		String second = String.format("%02d", sequenceDateTime.getSecond());
		String nano = String.format("%09d", sequenceDateTime.getNano());
		String refundSequenceNo = year + month + day + hour + minute + second + nano;
		//遍历统计退款金额
		double refundPrice = 0.0;
		for (RefundRequest refundRequest : refundRequests) {
			String sequenceNo = refundRequest.getSequenceNo();
			String itemBarcode = refundRequest.getItemBarcode();
			Item item = itemService.findItemByBarcode(itemBarcode);
			TurnoverFlow turnoverFlow = turnoverFlowService.findFlowWithItemBarcode(sequenceNo, itemBarcode);
			Double refundRequestQuantity = refundRequest.getQuantity();
			//获取退款商品的价格和收益
			Double price = item.getPrice();
			double profit = price - item.getPurchasePrice();
			refundPrice += price;
			//获取收款流水的收银员
			String userID = turnoverFlow.getUserID();
			//添加退款流水
			turnoverFlowService.addFlow(refundSequenceNo, sequenceDateTime, userID, itemBarcode, -1, price,
					refundRequestQuantity, profit, handlerID, sequenceNo);
		}
		//构造并返回响应体
		Map<String, Object> refundResponseMap = new HashMap<>();
		refundResponseMap.put("refundPrice", refundPrice);
		return new ResponseResult<>(10200, "OK", refundResponseMap);
	}

}
